﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Text;
using EnCor.Config;
using EnCor.ServiceLocator;
using EnCor.ModuleLoader;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.PolicyInjection;
using Microsoft.Practices.EnterpriseLibrary.PolicyInjection.Configuration;

namespace EnCor
{
    public class ModuleConfigContext : IModuleContext
    {
        private ModuleConfig _Config;
        private List<PolicyData> _InjectionPolicies = new List<PolicyData>();

        private IServiceContainer _ServiceContainer;

        public ModuleConfigContext(IServiceContainer container,ModuleConfig config)
        {
            _ServiceContainer = container;
            _Config = config;
        }

        public IServiceContainer ServiceContainer
        {
            get
            {
                return _ServiceContainer;
            }
        }

        public ModuleConfig Config
        {
            get
            {
                return _Config;
            }
        }

        public void AddPolicy(PolicyData policyData)
        {
            _InjectionPolicies.Add(policyData);
        }

        private IConfigurationSource BuildEnterpriseLibraryConfiguration()
        {
            DictionaryConfigurationSource source = new DictionaryConfigurationSource();
            PolicyInjectionSettings policyInjectionSetting = new PolicyInjectionSettings();
            foreach (PolicyData policyData in _InjectionPolicies)
            {
                policyInjectionSetting.Policies.Add(policyData);
            }

            source.Add("policyInjection", policyInjectionSetting);

            return source;
        }

        #region IModuleContext 成员

        public BizService RegisterBizService(BizService service, params Type[] asInterfaces)
        {
            foreach ( Type type in asInterfaces)
            {
                if (!type.IsAssignableFrom(service.GetType()))
                {
                    throw new EnCorException(string.Format("The BizService {0} cannot be registered as {1}", service, type));
                }
                _ServiceContainer.RegisterService(type, service);
            }
            return service;
        }

        public BizService BuildService(ServiceConfig serviceConfig)
        {
            ServiceBuilder serviceBuilder = new ServiceBuilder(_ServiceContainer);
            BizService bizService = serviceBuilder.BuildService(serviceConfig);

            IConfigurationSource piConfigurationSource = BuildEnterpriseLibraryConfiguration();
            BizService proxy = PolicyInjection.Wrap<BizService>(piConfigurationSource, bizService);

            return proxy;
        }

        #endregion
    }
}
